testsuite: use SysprofProfiler for profiling
authorChristian Hergert <chergert@redhat.com>
Fri, 21 Aug 2020 20:49:14 +0000 (13:49 -0700)
committerChristian Hergert <chergert@redhat.com>
Fri, 21 Aug 2020 20:51:52 +0000 (13:51 -0700)
Instead of using sysprof-cli to profile subprocesses, this uses
libsysprof's SysprofProfiler directly so that we can avoid an indirect
subprocess as well as disabling the polkit nag.

To do this, we have to link against libsysprof instead of
libsysprof-capture. This is limited to the -Dbuild-tests=true and
-Dprofiler=true case.

meson.build
testsuite/performance/test-performance.c

index 7b32667bf932579cab14887c97a9617e0d18229f..5884b259e9cb9cf5fb06085b1ef6bfd9f556edb4 100644 (file)
@@ -703,20 +703,34 @@ endif
 
 profiler_enabled = get_option('profiler')
 if profiler_enabled
-  # libsysprof-capture support
-  profiler_dep = dependency('sysprof-capture-4',
+  # Depend on libsysprof-capture if we only need the capture format.
+  # For -Dbuild-tests=true, we need SysprofProfiler to profile processes
+  # which requires sysprof-4 instead of sysprof-capture-4.
+
+  profiler_options = [
+    'enable_examples=false',
+    'enable_gtk=false',
+    'enable_tests=false',
+    'enable_tools=false',
+    'with_sysprofd=none',
+    'help=false',
+  ]
+
+  if get_option('build-tests')
+    profiler_dep_name = 'sysprof-4'
+    profiler_fallback = 'libsysprof_dep'
+  else
+    profiler_dep_name = 'sysprof-capture-4'
+    profiler_fallback = 'libsysprof_capture_dep'
+    profiler_options += ['libsysprof=false']
+  endif
+
+  profiler_dep = dependency(profiler_dep_name,
     required: true,
-    default_options: [
-      'enable_examples=false',
-      'enable_gtk=false',
-      'enable_tests=false',
-      'enable_tools=false',
-      'libsysprof=false',
-      'with_sysprofd=none',
-      'help=false',
-    ],
-    fallback: ['sysprof', 'libsysprof_capture_dep'],
+    default_options: profiler_options,
+    fallback: ['sysprof', profiler_fallback],
   )
+
   if profiler_dep.found()
     cdata.set('HAVE_SYSPROF', profiler_dep.found())
   else
index b6b53de2d1da82f33f41000136190fcfff44b743..5b93c0d50733b3904b6b84c083d79e0fa83e9424 100644 (file)
@@ -1,9 +1,10 @@
+#include <errno.h>
 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <errno.h>
-#include <sysprof-capture.h>
+#include <sysprof.h>
 #include <gio/gio.h>
 
 typedef struct {
@@ -46,6 +47,8 @@ static char *opt_detail;
 static char *opt_name;
 static char *opt_output;
 static gboolean opt_start_time;
+static GMainLoop *main_loop;
+static GError *failure;
 
 static GOptionEntry options[] = {
   { "mark", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &opt_mark, "Name of the mark", "NAME" },
@@ -57,6 +60,29 @@ static GOptionEntry options[] = {
   { NULL, }
 };
 
+static gboolean
+start_in_main (gpointer data)
+{
+  SysprofProfiler *profiler = data;
+  sysprof_profiler_start (profiler);
+  return G_SOURCE_REMOVE;
+}
+
+static void
+on_failure_cb (SysprofProfiler *profiler,
+               const GError    *error)
+{
+  g_propagate_error (&failure, g_error_copy (error));
+  g_main_loop_quit (main_loop);
+}
+
+static void
+on_stopped_cb (SysprofProfiler *profiler)
+{
+  g_clear_error (&failure);
+  g_main_loop_quit (main_loop);
+}
+
 int
 main (int argc, char *argv[])
 {
@@ -68,7 +94,9 @@ main (int argc, char *argv[])
   gint64 min, max, total;
   int count;
   char *output_dir = NULL;
-  int i;
+  char **spawn_env;
+  char *workdir;
+  int i, j;
 
   context = g_option_context_new ("COMMANDLINE");
   g_option_context_add_main_entries (context, options, NULL);
@@ -84,6 +112,12 @@ main (int argc, char *argv[])
   if (opt_rep < 1)
     g_error ("COUNT must be a positive number");
 
+  main_loop = g_main_loop_new (NULL, FALSE);
+  workdir = g_get_current_dir ();
+
+  spawn_env = g_get_environ ();
+  spawn_env = g_environ_setenv (spawn_env, "GTK_DEBUG_AUTO_QUIT", "1", TRUE);
+
   if (opt_output)
     {
       GError *err = NULL;
@@ -116,10 +150,10 @@ main (int argc, char *argv[])
 
   for (i = 0; i < opt_rep; i++)
     {
-      GSubprocessLauncher *launcher;
-      GSubprocess *subprocess;
+      SysprofProfiler *profiler;
       int fd;
       char *name;
+      SysprofCaptureWriter *writer;
       SysprofCaptureReader *reader;
       SysprofCaptureCursor *cursor;
       SysprofCaptureCondition *condition;
@@ -128,40 +162,42 @@ main (int argc, char *argv[])
       fd = g_file_open_tmp ("gtk.XXXXXX.syscap", &name, &error);
       if (error)
         g_error ("Create syscap file: %s", error->message);
-      close (fd); // sysprof-cli uses O_EXCL
-
-      child_argv = g_new (char *, argc + 6);
-      child_argv[0] = (char *)"sysprof-cli";
-      child_argv[1] = (char *)"--force";
-      child_argv[2] = (char *)"--use-trace-fd";
-      child_argv[3] = name;
-      child_argv[4] = (char *)"--";
-      for (i = 0; i + 1 < argc; i++)
-        child_argv[5 + i] = argv[i + 1];
-      child_argv[5 + argc - 1] = NULL;
-
-      launcher = g_subprocess_launcher_new (0);
-      g_subprocess_launcher_setenv (launcher, "GTK_DEBUG_AUTO_QUIT", "1", TRUE);
-
-      subprocess = g_subprocess_launcher_spawnv (launcher, (const char *const *)child_argv, &error);
-      if (error)
-        g_error ("Launch child: %s", error->message);
 
+      child_argv = g_new (char *, argc);
+      for (j = 0; j + 1 < argc; j++)
+        child_argv[j] = argv[j + 1];
+      child_argv[argc - 1] = NULL;
+
+      writer = sysprof_capture_writer_new_from_fd (fd, 0);
+      if (!writer)
+        g_error ("Failed to create capture writer: %s", g_strerror (errno));
+
+      profiler = sysprof_local_profiler_new ();
+      sysprof_profiler_set_whole_system (profiler, FALSE);
+      sysprof_profiler_set_spawn (profiler, TRUE);
+      sysprof_profiler_set_spawn_argv (profiler, (const char * const *)child_argv);
+      sysprof_profiler_set_spawn_cwd (profiler, workdir);
+      sysprof_profiler_set_spawn_env (profiler, (const char * const *)spawn_env);
+      sysprof_profiler_set_writer (profiler, writer);
+
+      sysprof_capture_writer_unref (writer);
       g_free (child_argv);
 
-      if (!g_subprocess_wait (subprocess, NULL, &error))
-        g_error ("Run child: %s", error->message);
+      g_signal_connect_swapped (profiler, "failed", G_CALLBACK (on_failure_cb), NULL);
+      g_signal_connect_swapped (profiler, "stopped", G_CALLBACK (on_stopped_cb), NULL);
 
-      if (!g_subprocess_get_successful (subprocess))
-        g_error ("Child process failed");
+      g_idle_add (start_in_main, profiler);
+      g_main_loop_run (main_loop);
 
-      g_object_unref (subprocess);
-      g_object_unref (launcher);
+      if (failure)
+        g_error ("Run child: %s", failure->message);
 
-      reader = sysprof_capture_reader_new (name);
+      reader = sysprof_capture_writer_create_reader (writer);
       if (!reader)
         g_error ("Opening syscap file: %s", g_strerror (errno));
 
+      sysprof_capture_writer_unref (writer);
+
       data.mark = opt_mark ? opt_mark : "css validation";
       data.detail = opt_detail ? opt_detail : NULL;
       data.do_start = opt_start_time;
@@ -206,6 +242,8 @@ main (int argc, char *argv[])
       g_usleep (300000);
     }
 
+  g_free (workdir);
+
   min = G_MAXINT64;
   max = 0;
   count = 0;